package com.xcity.robot.net.websocket;

import static naga.x.net.impl.websocket.WebSocketConst.PLAYLOAD_LEN_2_BYTES;
import static naga.x.net.impl.websocket.WebSocketConst.PLAYLOAD_LEN_8_BYTES;
import static naga.x.net.impl.websocket.WebSocketConst.PLAYLOAD_LEN_MASK;

import java.nio.ByteBuffer;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;

import naga.x.net.impl.websocket.WebSocketConst;
import naga.x.util.IoBufferWrapper;

public class WebsocketEncoder extends ProtocolEncoderAdapter {

	public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
		IoBuffer msg = wrap(message);
		int msgLen = msg.limit();
		IoBuffer buf = IoBuffer.allocate(msgLen + 10);
		buf.put(WebSocketConst.OP_BINARY);
		// no mask
		if (msgLen < WebSocketConst.PLAYLOAD_LEN_2_BYTES) {
			buf.put((byte) msgLen);
		} else if (msgLen < 65536) {
			buf.put((byte) (PLAYLOAD_LEN_2_BYTES & PLAYLOAD_LEN_MASK));
			buf.putShort((short) msgLen);
		} else {
			buf.put((byte) (PLAYLOAD_LEN_8_BYTES & PLAYLOAD_LEN_MASK));
			buf.putLong(msgLen);
		}
		buf.put(msg);
		buf.flip();
		out.write(buf);
	}
	
	private IoBuffer wrap(Object message) {
		if (message instanceof byte[]) {
			return IoBuffer.wrap((byte[]) message);
		}
		if (message instanceof ByteBuffer) {
			return IoBuffer.wrap((ByteBuffer) message);
		}
		if (message instanceof IoBufferWrapper) {
			return ((IoBufferWrapper) message).buf();
		}
		throw new IllegalArgumentException("Can't wrap the message: " + (message != null ? message.getClass() : null) + " -> " + message);
	}

}
